package momo.multitree.simulation;

import momo.multitree.algo.EdmundAlgo;
import momo.multitree.algo.KrzyAlgo;
import momo.multitree.algo.LatencyShortestPath;
import momo.multitree.structure.Graph;
import momo.multitree.structure.Tree;

public abstract class TreeOptAlg {

	protected Tree bestLatTree;
	protected Tree bestCostTree;
	protected Tree bestStabTree;
	protected Tree initBestTree;
	private double bestLat;
	private double bestCost;
	private double bestStab;
	private double worstLat;
	private double worstCost;
	private double worstStab;
	private double minDist = Double.POSITIVE_INFINITY;

	protected Graph g;
	
	public TreeOptAlg(Graph g) {
		super();
		this.g= g;
		LatencyShortestPath latTest = new LatencyShortestPath();
		bestLatTree = latTest.optimumTree(g);
		
		KrzyAlgo costTest = new KrzyAlgo(g);
		bestCostTree = costTest.optimumTree();
		
		EdmundAlgo stabTest = new EdmundAlgo(g);
		bestStabTree = stabTest.optimumTree();
		
		bestLat = bestLatTree.compWeightedLatency();
		worstLat = bestCostTree.compWeightedLatency() > bestStabTree.compWeightedLatency() ? bestCostTree.compWeightedLatency() :  bestStabTree.compWeightedLatency();
		
		bestCost = bestCostTree.compCost(false);
		worstCost = bestLatTree.compCost(false) > bestStabTree.compCost(false) ? bestLatTree.compCost(false) : bestStabTree.compCost(false);  
		
		bestStab = bestStabTree.compStability();
		worstStab = bestLatTree.compStability() > bestCostTree.compStability() ? bestLatTree.compStability() : bestCostTree.compStability();		
	}

	
	public Tree getBestLatTree() {
		return bestLatTree;
	}

	public Tree getBestCostTree() {
		return bestCostTree;
	}

	public Tree getBestStabTree() {
		return bestStabTree;
	}

	protected double scoreLen(Tree t) {
		double latT, costT, stabT;
		double lat = t.compWeightedLatency();
		double cost = t.compCost(false);
		double stab = t.compStability();
		
		latT = ( lat - bestLat ) / ( worstLat - bestLat );
		if ( Double.isNaN(latT) || Double.isInfinite(latT) ) latT = 0;
		
		costT = ( cost - bestCost ) / ( worstCost - bestCost );
		if ( Double.isNaN(costT) || Double.isInfinite(costT) ) costT = 0;
		
		stabT = ( stab - bestStab ) / ( worstStab - bestStab );
		if ( Double.isNaN(stabT) || Double.isInfinite(stabT) ) stabT = 0;
		
		double dist = Math.sqrt( Math.pow(latT, 2) + Math.pow(costT, 2) + Math.pow(stabT, 2) );
		return dist;
	}
	
	public abstract Tree optimizeTree();

}